/*
 * @Description: 
 * @Autor: ilmari
 * @Date: 2021-05-18 09:32:28
 * @LastEditors: ilmari
 * @LastEditTime: 2021-05-18 10:23:39
 */
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:rcmd/app/modules/rcmd/controllers/custom_controller.dart';
import 'package:rcmd/app/modules/rcmd/models/rlog.dart';
import '../controllers/rcmd_controller.dart';
import 'persist_page.dart';

class CustomCmdPage extends PersistPage<CustomCmdController> {
  CustomCmdPage(String key, {List<String>? selIpList})
      : super(key, CustomCmdController(selIpList: selIpList));

  @override
  Widget build(BuildContext context) {
    final scroll = ScrollController();
    final focuseNode = FocusNode();
    bool search = false;
    bool resever = false;
    GlobalKey listKey = GlobalKey();
    return GestureDetector(
      child: RawKeyboardListener(
          focusNode: focuseNode,
          autofocus: true,
          onKey: (evt) {
            if (evt.runtimeType == RawKeyDownEvent) {
              search = evt.isKeyPressed(LogicalKeyboardKey.f3);
              resever = evt.isShiftPressed;
            } else if (evt.runtimeType == RawKeyUpEvent) {
              if (search) {
                final txt = Get.find<RcmdController>().filter.value;
                if (txt.isNotEmpty) {
                  final box = listKey.currentContext?.findRenderObject();
                  final rect = box?.semanticBounds;
                  final off = (rect?.height ?? 25 * 30) / 2;
                  int index = (scroll.offset + off) ~/ 25;
                  index = controller.searchText(txt, index, resever);
                  if (index >= 0) {
                    scroll.jumpTo(index * 25 - off);
                  }
                }
              }
            }
          },
          child: Container(
              child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              _cmdBar1(context),
              _cmdBar2(context),
              Expanded(child: Obx(() {
                final count = controller.dispLinesCount.value;
                return ListView.builder(
                  key: listKey,
                  addAutomaticKeepAlives: false,
                  addRepaintBoundaries: false,
                  itemCount: count,
                  itemExtent: 25,
                  controller: scroll,
                  itemBuilder: (BuildContext context, int index) {
                    return _makeRlogLine(controller.dispLinesAt(index));
                  },
                );
              }))
            ],
          ))),
      onTap: () {
        focuseNode.requestFocus();
      },
    );
  }

  Widget _cmdBar1(BuildContext context) {
    return Row(children: [
      Obx(() => Row(
            mainAxisSize: controller.allSelectListLength.value > 0
                ? MainAxisSize.min
                : MainAxisSize.min,
            children: controller.allSelectList
                .map((ip) =>
                    padding(Text(ip), vertical: 0, horizontal: 3) as Widget)
                .followedBy([
              IconButton(
                  onPressed: () {
                    _addDstIp(context);
                  },
                  icon: Icon(Icons.add))
            ]).toList(),
          )),
      Expanded(child: Obx(()=>Row(
        mainAxisAlignment: controller.dispFilterCount.value == -1
          ? MainAxisAlignment.start
          : MainAxisAlignment.end,
        children: filterViewList.toList(),
      ))),
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Obx(()=>Text("${controller.dispLinesCount}/${controller.allLinesCount}")),
            padding(Text("前"), vertical: 0, horizontal: 5),
            ConstrainedBox(constraints: BoxConstraints(maxWidth: 50, maxHeight: 20), child:textField("0", (nv, over) { 
              controller.beforeCnt = int.tryParse(nv)??0;
            }, keyboardType: TextInputType.number)),
            padding(Text("后"), vertical: 0, horizontal: 5),
            ConstrainedBox(constraints: BoxConstraints(maxWidth: 50, maxHeight: 20), child:textField("0", (nv, over) { 
              controller.afterCnt = int.tryParse(nv)??0;
            }, keyboardType: TextInputType.number)),
            padding(TextButton(
              onPressed: controller.applyFilters,
              child: Text("应用规则")),
            vertical: 0,
            horizontal: 10),
            TextButton( onPressed: controller.removeAllLogLines, child: Text("清空内容"))
          ],)
    ]);
  }

  Widget _cmdBar2(BuildContext context) {
    String inputText = "";
    final removeDropdown = 0.obs;
    return Row(
      children: [
        Expanded(child: 
        ConstrainedBox(
            constraints: BoxConstraints(maxHeight: 75.0),  //父组件 
            child: autoCompleteTextFeild(context, "", (val, over) {
          inputText = val;
          if (over) _excuteCmd(val);
        }, controller.getMatchCmd, removeDropdown: removeDropdown, keyboardType: TextInputType.multiline))),
        IconButton(
          onPressed: () {
            removeDropdown.value++;
            _excuteCmd(inputText);
          },
          icon: Icon(Icons.send_outlined))
      ],
    );
  }

  void _addDstIp(BuildContext context) async {
    var sel = await selFromList(context, ["节点", "集群"]);
    if (sel < 0) return;
    late List<String> ips;
    late List<String> selIps;
    if (sel == 0) {
      ips = controller.allIpListNotInCluster.toList();
      selIps = controller.allSelectList.toList(growable: false);
    } else {
      final clusters = controller.allClusterList.toList();
      sel = await selFromList(context, clusters);
      if (sel == -1) return;
      ips = controller.getIpListByCluster(clusters[sel]) ?? [];
      selIps = ips.toList(growable: false);
    }
    //sel = await selFromList(context, ips);
    //controller.addToSelectIp([ips[sel]]);
    var sels = await selectStringList(ips, selIps);
    if (sels != null) {
      controller.assignSelectIp(sels);
    }
  }

  Widget _makeRlogLine(Rlogline line) {
    if (line.runtimeType == RlogSection) {
      final color = (line as RlogSection).finish ? Colors.green : Colors.red;
      return Center(
          child: Text.rich(TextSpan(
              children: [line.textSpan],
              style: TextStyle(color: color, fontWeight: FontWeight.w800))));
    }
    return SelectableText.rich(line.textSpan);
  }

  void _excuteCmd(String cmd) async {
    controller.abortPendingCmd();
    if (cmd.length == 0) return;
    Stopwatch watch = Stopwatch();
    printInfo(info: "${DateTime.now()} cmd=$cmd");
    watch.start();
    Timer? timer;
    bool needFresh = false;
    timer = Timer.periodic(Duration(milliseconds: 500), (t) {
      if (needFresh) controller.refresh();
    });
    controller.allSelectList.forEach((ip) {
      final sec = controller.addSection("[$ip] ---- $cmd");
      controller.shellAsync(ip, cmd, (lines) {
        needFresh = true;
        controller.addLines(lines, section: sec, fresh: false);
      }, (res) {
        timer?.cancel();
        printInfo(info: "${DateTime.now()} $ip: over, res=${res.msg}");
        controller.finishAdd(sec);
        if (!res.ok) Get.snackbar("错误", res.msg);
      }).then((abort) {
        sec.dat = abort;
      });
    });
  }

  Iterable<Widget> get filterViewList {
    return controller.dispFilters.map((e) => IconButton(
        onPressed: () {},
        tooltip: e.toString(),
        icon: GestureDetector(
          child: Icon(
            Icons.delete_outline,
            color: e.enable
                ? e.isExclude
                    ? Colors.redAccent
                    : Colors.greenAccent
                : Colors.grey,
          ),
          onTap: () {
            controller.enableFilter(e, !e.enable);
          },
          onDoubleTap: () {
            controller.deleteDispFilter(e);
          },
        )));
  }
}
